﻿using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Jobs;
using Random = UnityEngine.Random;

public class JobTest2 : MonoBehaviour
{
    public class MoveData
    {
        public Transform Actor;
        public float MoveY;
    }

    public bool isJob;
    
    public Transform Prefab;
    public List<MoveData> MoveDatas;
    private TransformAccessArray accessArray;
    private NativeArray<float> moveYlist;
    private void Start()
    {
        this.MoveDatas = new List<MoveData>();
        
        for (int i = 0; i < 10000; i++)
        {
            Transform mover = Instantiate(this.Prefab, new Vector3(Random.Range(-8f, 8f), Random.Range(-5f, 5f), 0), Quaternion.identity);
            mover.gameObject.GetComponent<SpriteRenderer>().color = new Color(Random.value , Random.value, Random.value);
            this.MoveDatas.Add(new MoveData()
                               {
                                   Actor = mover,
                                   MoveY = Random.Range(1f , 2.5f)
                               });
        }

        accessArray = new TransformAccessArray(0 , 64);
        moveYlist   = new NativeArray<float>(this.MoveDatas.Count , Allocator.Persistent);
        for (int i = 0; i < this.MoveDatas.Count; i++)
        {
            this.accessArray.Add(this.MoveDatas[i].Actor);
            this.moveYlist[i] = this.MoveDatas[i].MoveY;
        }
    }

    public void SetJobWork(bool isJob) { this.isJob = isJob; }

    private void Update()
    {
        if (this.isJob)
        {
            JobMove jobMove = new JobMove()
                              {
                                  DealtTime = Time.deltaTime,
                                  MoveYs = moveYlist
                              };
            JobHandle handle = jobMove.Schedule(accessArray);
            handle.Complete();
        }
        else
        {
            this.NormalMove();
        }
    }

    private void OnDisable()
    {
        this.moveYlist.Dispose();
        this.accessArray.Dispose();
    }

    public void NormalMove()
    {
        for (int i = 0; i < this.MoveDatas.Count; i++)
        {
            this.MoveDatas[i].Actor.position += new Vector3(0 , this.MoveDatas[i].MoveY * Time.deltaTime);
            this.MoveDatas[i].Actor.rotation = Quaternion.Euler(this.MoveDatas[i].Actor.rotation.eulerAngles + Vector3.forward * 2.5f);
            float value = 0f;
            for (int j = 0; j < 100; j++)
            {
                value = math.exp10(math.sqrt(value));
            }
            if (this.MoveDatas[i].Actor.position.y >= 5)
            {
                this.MoveDatas[i].MoveY = -math.abs(this.MoveDatas[i].MoveY);
            }
            else if(this.MoveDatas[i].Actor.position.y <= -5)
            {
                this.MoveDatas[i].MoveY = math.abs(this.MoveDatas[i].MoveY);
            }
        }
    }
    
    [BurstCompile]
    public struct JobMove : IJobParallelForTransform
    {
        [ReadOnly]
        public float DealtTime;
        public NativeArray<float> MoveYs;
        public void Execute(int index, TransformAccess transform)
        {
            transform.position = new float3(transform.position.x , transform.position.y + this.DealtTime * this.MoveYs[index] , transform.position.z);
            transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles + Vector3.forward * 2.5f);
            float value = 0f;
            for (int j = 0; j < 100; j++)
            {
                value = math.exp10(math.sqrt(value));
            }
            if (transform.position.y >= 5)
            {
                this.MoveYs[index] = -math.abs(this.MoveYs[index]);
            }
            else if(transform.position.y <= -5)
            {
                this.MoveYs[index] = math.abs(this.MoveYs[index]);
            }
        }
    }
}
